// Cz LLVM 后端
// 将 Cz IR 转换为 LLVM IR

const std = @import("std");
const parser = @import("parser.zig");

/// LLVM IR 生成器
pub const LLVMBackend = struct {
    allocator: std.mem.Allocator,
    module_name: []const u8,
    
    pub fn init(allocator: std.mem.Allocator, module_name: []const u8) LLVMBackend {
        return .{
            .allocator = allocator,
            .module_name = module_name,
        };
    }
    
    /// 生成 LLVM IR
    pub fn generate(self: *LLVMBackend, ast: parser.AST) ![]const u8 {
        var ir = std.ArrayList(u8).init(self.allocator);
        const writer = ir.writer();
        
        // LLVM IR 头部
        try writer.print("; ModuleID = '{s}'\n", .{self.module_name});
        try writer.writeAll("source_filename = \"" ++ self.module_name ++ "\"\n");
        try writer.writeAll("target datalayout = \"e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128\"\n");
        try writer.writeAll("target triple = \"x86_64-pc-linux-gnu\"\n\n");
        
        // 声明外部函数
        try writer.writeAll("; External declarations\n");
        try writer.writeAll("declare i32 @printf(i8*, ...)\n");
        try writer.writeAll("declare i8* @malloc(i64)\n");
        try writer.writeAll("declare void @free(i8*)\n\n");
        
        // 生成函数
        try writer.writeAll("; Functions\n");
        for (ast.functions) |func| {
            try self.generateFunction(writer, func);
        }
        
        // 生成 Actor
        try writer.writeAll("\n; Actors\n");
        for (ast.actors) |actor| {
            try self.generateActor(writer, actor);
        }
        
        return ir.toOwnedSlice();
    }
    
    fn generateFunction(self: *LLVMBackend, writer: anytype, func: parser.Function) !void {
        _ = self;
        
        const visibility = if (func.is_pub) "" else "internal ";
        
        try writer.print("define {s}void @{s}() {{\n", .{visibility, func.name});
        try writer.writeAll("entry:\n");
        
        // 简单的函数体（Hello World）
        try writer.writeAll("  %str = alloca [20 x i8]\n");
        try writer.writeAll("  %str_ptr = getelementptr [20 x i8], [20 x i8]* %str, i32 0, i32 0\n");
        try writer.writeAll("  call i32 (i8*, ...) @printf(i8* %str_ptr)\n");
        try writer.writeAll("  ret void\n");
        try writer.writeAll("}\n\n");
    }
    
    fn generateActor(self: *LLVMBackend, writer: anytype, actor: parser.Actor) !void {
        _ = self;
        
        // Actor 结构体定义
        try writer.print("; Actor: {s}\n", .{actor.name});
        try writer.print("%{s} = type {{ ", .{actor.name});
        
        for (actor.fields, 0..) |field, i| {
            if (i > 0) try writer.writeAll(", ");
            try writer.print("i32", .{}); // 简化：所有字段都是 i32
            _ = field;
        }
        
        try writer.writeAll(" }\n\n");
        
        // Actor 初始化函数
        try writer.print("define %{s}* @{s}_init() {{\n", .{actor.name, actor.name});
        try writer.writeAll("entry:\n");
        try writer.writeAll("  %actor = call i8* @malloc(i64 16)\n");
        try writer.print("  %typed = bitcast i8* %actor to %{s}*\n", .{actor.name});
        try writer.writeAll("  ret %{s}* %typed\n", .{actor.name});
        try writer.writeAll("}\n\n");
    }
};

/// 生成 LLVM IR 文件
pub fn generateLLVMIR(
    allocator: std.mem.Allocator,
    ast: parser.AST,
    output_path: []const u8,
) !void {
    var backend = LLVMBackend.init(allocator, "cz_module");
    const ir = try backend.generate(ast);
    defer allocator.free(ir);
    
    try std.fs.cwd().writeFile(output_path, ir);
}
